package com.ryder.petmatediarybackend.module.auth.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import com.ryder.petmatediarybackend.common.response.Result;
import com.ryder.petmatediarybackend.module.auth.dto.RoleDTO;
import com.ryder.petmatediarybackend.module.auth.dto.RolePermissionDTO;
import com.ryder.petmatediarybackend.module.auth.service.SysRolePermissionService;
import com.ryder.petmatediarybackend.module.auth.service.SysRoleService;
import com.ryder.petmatediarybackend.module.auth.vo.PermissionVO;
import com.ryder.petmatediarybackend.module.auth.vo.RoleVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 描述：角色管理 + 角色权限管理 Controller
 *
 * @author Ryder
 * @version 1.0
 * @since 1.0
 * 更新日期: 2025/10/28
 */
@Slf4j
@Tag(name = "角色管理", description = "角色管理和角色权限管理接口（需要登录 + 平台管理员角色 + 对应权限）")
@RestController
@RequestMapping("/admin/role")
@SaCheckRole("ROLE_PLATFORM_ADMIN")
@SecurityRequirement(name = "Authorization")
@RequiredArgsConstructor
public class AdminRoleController {

    private final SysRoleService sysRoleService;

    private final SysRolePermissionService sysRolePermissionService;

    // ==================== 角色管理 ====================

    @Operation(summary = "新增角色", description = "创建新的系统角色，需要 system:role:add 权限")
    @SaCheckPermission("system:role:add")
    @PostMapping("/add")
    public Result<RoleVO> addRole(@Valid @RequestBody RoleDTO dto) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色管理] 用户ID={} 执行新增角色, 方法=addRole, 入参={}", userId, dto);
        RoleVO vo = sysRoleService.addRole(dto);
        log.info("[角色管理] 用户ID={} 新增角色成功, 角色ID={}, 角色编码={}", userId, vo.getId(), vo.getCode());
        return Result.ok(vo);
    }

    @Operation(summary = "更新角色", description = "修改指定角色的信息，需要 system:role:edit 权限")
    @SaCheckPermission("system:role:edit")
    @PutMapping("/update/{id}")
    public Result<RoleVO> updateRole(@PathVariable Long id, @Valid @RequestBody RoleDTO dto) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色管理] 用户ID={} 执行更新角色, 方法=updateRole, 角色ID={}, 入参={}", userId, id, dto);
        RoleVO vo = sysRoleService.updateRole(id, dto);
        log.info("[角色管理] 用户ID={} 更新角色成功, 角色ID={}, 角色编码={}", userId, vo.getId(), vo.getCode());
        return Result.ok(vo);
    }

    @Operation(summary = "删除角色", description = "删除指定角色（逻辑删除），需要 system:role:delete 权限")
    @SaCheckPermission("system:role:delete")
    @DeleteMapping("/delete/{id}")
    public Result<Void> deleteRole(@PathVariable Long id) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色管理] 用户ID={} 执行删除角色, 方法=deleteRole, 角色ID={}", userId, id);
        sysRoleService.deleteRole(id);
        log.info("[角色管理] 用户ID={} 删除角色成功, 角色ID={}", userId, id);
        return Result.ok();
    }

    @Operation(summary = "查询角色列表", description = "获取所有角色列表，需要 system:role:view 权限")
    @SaCheckPermission("system:role:view")
    @GetMapping("/list")
    public Result<List<RoleVO>> listRoles() {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色管理] 用户ID={} 执行查询角色列表, 方法=listRoles", userId);
        List<RoleVO> list = sysRoleService.listRoles();
        log.info("[角色管理] 用户ID={} 查询角色列表成功, 数量={}", userId, list.size());
        return Result.ok(list);
    }

    @Operation(summary = "查询角色详情", description = "根据ID查询角色详细信息，需要 system:role:view 权限")
    @SaCheckPermission("system:role:view")
    @GetMapping("/{id}")
    public Result<RoleVO> getRoleById(@PathVariable Long id) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色管理] 用户ID={} 执行查询角色详情, 方法=getRoleById, 角色ID={}", userId, id);
        RoleVO vo = sysRoleService.getRoleById(id);
        return Result.ok(vo);
    }

    // ==================== 角色权限管理 ====================

    @Operation(summary = "分配角色权限", description = "为指定角色分配权限，需要 system:role:permission:assign 权限")
    @SaCheckPermission("system:role:permission:assign")
    @PostMapping("/permission/assign")
    public Result<Void> assignPermissions(@Valid @RequestBody RolePermissionDTO dto) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色权限] 用户ID={} 执行分配角色权限, 方法=assignPermissions, 入参={}", userId, dto);
        sysRolePermissionService.assignPermissions(dto.getRoleId(), dto.getPermissionIds());
        log.info("[角色权限] 用户ID={} 分配角色权限成功, 角色ID={}, 权限数量={}", userId, dto.getRoleId(), dto.getPermissionIds().size());
        return Result.ok();
    }

    @Operation(summary = "移除角色权限", description = "移除指定角色的权限，需要 system:role:permission:remove 权限")
    @SaCheckPermission("system:role:permission:remove")
    @PostMapping("/permission/remove")
    public Result<Void> removePermissions(@Valid @RequestBody RolePermissionDTO dto) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色权限] 用户ID={} 执行移除角色权限, 方法=removePermissions, 入参={}", userId, dto);
        sysRolePermissionService.removePermissions(dto.getRoleId(), dto.getPermissionIds());
        log.info("[角色权限] 用户ID={} 移除角色权限成功, 角色ID={}, 权限数量={}", userId, dto.getRoleId(), dto.getPermissionIds().size());
        return Result.ok();
    }

    @Operation(summary = "查询角色权限列表", description = "查询指定角色拥有的所有权限，需要 system:role:permission:view 权限")
    @SaCheckPermission("system:role:permission:view")
    @GetMapping("/permission/list")
    public Result<List<PermissionVO>> getRolePermissions(@RequestParam Long roleId) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色权限] 用户ID={} 执行查询角色权限列表, 方法=getRolePermissions, 角色ID={}", userId, roleId);
        List<PermissionVO> list = sysRolePermissionService.getRolePermissions(roleId);
        log.info("[角色权限] 用户ID={} 查询角色权限列表成功, 角色ID={}, 权限数量={}", userId, roleId, list.size());
        return Result.ok(list);
    }

    @Operation(summary = "查询所有可用权限", description = "获取系统所有可用权限列表，需要 system:role:permission:view 权限")
    @SaCheckPermission("system:role:permission:view")
    @GetMapping("/permission/all")
    public Result<List<PermissionVO>> listAllPermissions() {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("[角色权限] 用户ID={} 执行查询所有可用权限, 方法=listAllPermissions", userId);
        List<PermissionVO> list = sysRolePermissionService.listAllPermissions();
        log.info("[角色权限] 用户ID={} 查询所有可用权限成功, 权限数量={}", userId, list.size());
        return Result.ok(list);
    }
}
